package com.leyou.auth.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.leyou.auth.config.JwtProperties;
import com.leyou.auth.domain.RoleVo;
import com.leyou.auth.domain.SysUser;
import com.leyou.auth.domain.UserVo;
import com.leyou.auth.mapper.UserMapper;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.CookieUtils;
import com.leyou.user.client.UserClient;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;
    private JwtProperties prop;



    public JwtLoginFilter(AuthenticationManager authenticationManager, JwtProperties prop) {
        //构造方法，在配置文件注入需要的属性，springsecurity的配置文件加载的顺序比较早，直接在这里注入属性会为空。
        this.authenticationManager = authenticationManager;
        this.prop = prop;

    }

    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //尝试登录认证
        try {

            SysUser sysUser = new ObjectMapper().readValue(request.getInputStream(), SysUser.class);
            //获取用户输入的用户名和密码
            Integer status = sysUser.getStatus();
            String username = sysUser.getUsername();
            //把区分的标志拼接到用户名区分后台用户和门户用户
            username = username + "&" + status;
            //创建UsernamePasswordAuthenticationToken
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, sysUser.getPassword());
            //认证的过程 跳转到UserService
            return authenticationManager.authenticate(authRequest);
        } catch (Exception e) {
            try {
                //异常说明用户名或密码错误，就是从数据库查询的用户数据为空
                response.setContentType("application/json;charset=utf-8");
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                PrintWriter out = response.getWriter();
                Map resultMap = new HashMap();
                resultMap.put("code", HttpServletResponse.SC_UNAUTHORIZED);
                resultMap.put("msg", "用户名或密码错误！");
                out.write(new ObjectMapper().writeValueAsString(resultMap));
                out.flush();
                out.close();
            } catch (Exception outEx) {
                outEx.printStackTrace();
            }
            throw new RuntimeException(e);
        }
    }

    public void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        //获取认证成功后的用户
        SysUser principal = (SysUser) authResult.getPrincipal();
        //转换一个类型
        UserVo userVo = new UserVo();
        userVo.setId(principal.getId());
        List<RoleVo> roleVos = BeanHelper.copyWithCollection(principal.getRoles(), RoleVo.class);
        userVo.setRoles(roleVos);
        userVo.setUsername(principal.getUsername());
        userVo.setStatus(principal.getStatus());
        //写进token
        String token = JwtUtils.generateTokenExpireInMinutes(userVo, prop.getPrivateKey(), 24 * 60);
        //response.addHeader("Authorization", "Bearer "+token);

        //写入浏览器Cookie中
        CookieUtils.newCookieBuilder()
                .response(response)
                .name(prop.getUser().getCookieName())
                .value(token)
                .domain(prop.getUser().getCookieDomain())
                .httpOnly(true)
                .build();
        try {
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            PrintWriter out = response.getWriter();
            Map resultMap = new HashMap();
            resultMap.put("code", HttpServletResponse.SC_OK);
            resultMap.put("msg", "认证通过！");
            out.write(new ObjectMapper().writeValueAsString(resultMap));
            out.flush();
            out.close();
        } catch (Exception outEx) {
            outEx.printStackTrace();
        }
    }

}
